package org.ediba.siri.core.publication.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.ediba.siri.core.Filter;
import org.ediba.siri.core.Util;
import org.ediba.siri.core.publication.data.PublicationCountryDao;
import org.ediba.siri.core.publication.data.PublicationDao;
import org.ediba.siri.core.publication.data.PublicationLevelDao;
import org.ediba.siri.core.publication.data.PublicationNumberDao;
import org.ediba.siri.core.publication.domain.Publication;
import org.ediba.siri.core.publication.domain.PublicationCountry;
import org.ediba.siri.core.publication.domain.PublicationLevel;
import org.ediba.siri.core.publication.domain.PublicationNumber;
import org.ediba.siri.core.user.service.UserService;

public class DefaultPublicationService implements PublicationService {

	private PublicationDao publicationDao;
	public void setPublicationDao(PublicationDao publicationDao) {this.publicationDao = publicationDao;}
	
	private PublicationCountryDao publicationCountryDao;
	public void setPublicationCountryDao(PublicationCountryDao publicationCountryDao) {this.publicationCountryDao = publicationCountryDao;}

	private PublicationLevelDao publicationLevelDao;
	public void setPublicationLevelDao(PublicationLevelDao publicationLevelDao) {this.publicationLevelDao = publicationLevelDao;}
	
	private PublicationNumberDao publicationNumberDao;
	public void setPublicationNumberDao(PublicationNumberDao publicationNumberDao) {this.publicationNumberDao = publicationNumberDao;}
	
	private UserService userService ;
	public void setUserService(UserService userService) {this.userService = userService;}

	/****************************PUBLICATION******************************/
	
	@Override
	public Publication create(int idPublicationCountry, String name) {
		PublicationCountry publicationCountry = this.publicationCountryDao.findById(idPublicationCountry);
		Publication publication = new Publication(publicationCountry, name);
		this.publicationDao.attachDirty(publication);
		return publication;
	}
	
	@Override
	public Publication retrieve(int id) {
		return this.publicationDao.findById(id);
	}
		
	@Override
	public Publication update(Publication publication) {
		this.publicationDao.attachDirty(publication);
		return publication;
	}
	
	@Override
	public boolean delete(int id) {
		return this.publicationDao.delete(id);
	}
	
	@Override
	public List<Publication> retrieve() {
		return this.publicationDao.getAll("name", true);
	}
	
	@Override
	public List<Publication> retrieve(String sort, boolean dir, int start,
			int limit) {
		return this.publicationDao.getAll(sort, dir, start, limit);
	}
	
	@Override
	public List<Publication> retrieveByParticipant(int idUser) {
		Set<Publication> publications = this.userService.retrieve(idUser).getPublications();
		return new ArrayList<Publication>(publications);
	}
	
	@Override
	public List<Publication> retrieveByResponsible(int idUser) {
		Set<Publication> publications = this.userService.retrieve(idUser).getPublications_1();
		return new ArrayList<Publication>(publications);
	}
	
	/****************************PUBLICATION NUMBER***********************/
	
	@Override
	public PublicationNumber numberCreate(int idPublication, int number){
		PublicationNumber publicationNumber = this.numberRetrieve(idPublication, number);
		if (publicationNumber == null){
			Publication publication = this.publicationDao.findById(idPublication);
			publicationNumber = new PublicationNumber(publication, number);
			this.publicationNumberDao.attachDirty(publicationNumber);
			return publicationNumber;
		}
		else 
			return null;
	}
	
	@Override
	public PublicationNumber numberRetrieve(int idPublication, int number){
		Collection<Map<Filter,Object>> filters = new HashSet<Map<Filter,Object>>(1);
		Map<Filter, Object> filter = new HashMap<Filter, Object>(2);
		
		filter.put(Filter.NUMBER, number);
		filter.put(Filter.PUBLICATION, idPublication);
		filters.add(filter);
		
		List<PublicationNumber> publicationNumbers = this.publicationNumberDao.findByFilters(filters, null, false);
		if (publicationNumbers.isEmpty())
			return null;
		else 
			return publicationNumbers.get(0);	
	}
	
	@Override
	public PublicationNumber numberRetrieve(int id) {
		return this.publicationNumberDao.findById(id);
	}

	@Override
	public PublicationNumber numberUpdate(PublicationNumber publicationNumber) {
		this.publicationNumberDao.attachDirty(publicationNumber);
		return publicationNumber;
	}
	
	@Override
	public boolean numberDelete(int id) {
		return this.publicationNumberDao.delete(id);
	}
	
	@Override
	public PublicationNumber numberRetrieveByPublication_last(int idPublication) {
		List<PublicationNumber> publicationNumbers = this.publicationNumberDao.findByFilters(Util.simpleFilter(Filter.PUBLICATION, idPublication), "number", false, 0, 1);
		if (publicationNumbers.isEmpty())
			return null;
		else
			return publicationNumbers.get(0);
	}
		
	@Override
	public List<PublicationNumber> numberRetrieve() {
		return this.publicationNumberDao.getAll(null, false);
	}
	
//	@Override
//	public List<PublicationNumber> numberRetrieveByPublication(int idPublication) {
//		return this.publicationNumberDao.findByFilters(Util.simpleFilter(Filter.PUBLICATION, idPublication), null, false);
//	}
//	
//	@Override
//	public List<PublicationNumber> numberRetrieveByPublication(int idPublication, String sort, boolean dir, int start, int limit) {
//		return this.publicationNumberDao.findByFilters(Util.simpleFilter(Filter.PUBLICATION, idPublication), sort, dir, start, limit);
//	}
	@Override
	public List<PublicationNumber> numberRetrieve(
			Map<Filter, Collection<Object>> filters, String sort, boolean dir) {
		return this.publicationNumberDao.findByFilters(filters, sort, dir);
	}

	@Override
	public int numberRetrieveCount(Map<Filter, Collection<Object>> filters) {
		return this.publicationNumberDao.findByFiltersCount(filters);
	}
	
	@Override
	public List<PublicationNumber> numberRetrieveByPublication_current(int idPublication) {
		Collection<Map<Filter,Object>> filters = new HashSet<Map<Filter,Object>>(1);
		Map<Filter, Object> filter = new HashMap<Filter, Object>(2);
		
		filter.put(Filter.DATE_MIN, new Date());
		filter.put(Filter.PUBLICATION, idPublication);
		filters.add(filter);
		
		return this.publicationNumberDao.findByFilters(filters, null, false);
	}

	@Override
	public List<PublicationNumber> numberRetrieveByImage(int idImage) {
		return this.publicationNumberDao.findByFilters(Util.simpleFilter(Filter.IMAGE, idImage), "date", true);
	}

	@Override
	public List<PublicationNumber> numberRetrieveByModel(int idModel) {
		return this.publicationNumberDao.findByFilters(Util.simpleFilter(Filter.MODEL, idModel), "date", true);
	}
	
	/****************************PUBLICATION COUNTRY***********************/
	
	@Override
	public PublicationCountry countryCreate(String code, String name) {
		PublicationCountry publicationCountry = new PublicationCountry(code, name);
		this.publicationCountryDao.attachDirty(publicationCountry);
		return publicationCountry;
	}
	
	@Override
	public PublicationCountry countryRetrieve(int id) {
		return this.publicationCountryDao.findById(id);
	}
	
	@Override
	public PublicationCountry countryUpdate(PublicationCountry publicationCountry) {
		this.publicationCountryDao.attachDirty(publicationCountry);
		return publicationCountry;
	}
	
	@Override
	public boolean countryDelete(int id) {
		return this.publicationCountryDao.delete(id);
	}
	
	@Override
	public List<PublicationCountry> countryRetrieve() {
		return this.publicationCountryDao.getAll(null, false);
	}

	@Override
	public PublicationLevel levelCreate(String name) {
		PublicationLevel publicationLevel = new PublicationLevel(name, false);
		this.publicationLevelDao.attachDirty(publicationLevel);
		return publicationLevel;
	}

	@Override
	public PublicationLevel levelRetrieve(int id) {
		PublicationLevel publicationLevel = this.publicationLevelDao.findById(id);
		return publicationLevel;
	}

	@Override
	public PublicationLevel levelUpdate(PublicationLevel publicationLevel) {
		this.publicationLevelDao.attachDirty(publicationLevel);
		return publicationLevel;
	}

	@Override
	public boolean levelDelete(int id) {
		return this.publicationLevelDao.delete(id);
	}

	@Override
	public List<PublicationLevel> levelRetrieve() {
		return this.publicationLevelDao.getAll(null, false);
	}

	@Override
	public List<Publication> retrieve(Map<Filter, Collection<Object>> filters,
			String sort, boolean dir) {
		return this.publicationDao.findByFilters(filters, sort, dir);
	}

	@Override
	public int retrieveCount(Map<Filter, Collection<Object>> filters) { 
		return this.publicationDao.findByFiltersCount(filters);
	}

	@Override
	public List<PublicationCountry> countryRetrieve(
			Map<Filter, Collection<Object>> filters, String sort, boolean dir) {
		return this.publicationCountryDao.findByFilters(filters, sort, dir);
	}

	@Override
	public int countryRetrieveCount(
			Map<Filter, Collection<Object>> filters) {
		return this.publicationCountryDao.findByFiltersCount(filters);
	}

}
